package com.boatAnchorAssistant.service.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.boatAnchorAssistant.pojo.dto.authorization.GetAuthorizedByTargetIdDto;
import com.boatAnchorAssistant.pojo.entity.Role;
import com.boatAnchorAssistant.pojo.event.role.DeleteRoleEvent;
import com.boatAnchorAssistant.pojo.param.authorization.AuthorizationParam;
import com.boatAnchorAssistant.pojo.param.role.*;
import com.boatAnchorAssistant.pojo.vo.role.*;
import com.boatAnchorAssistant.pojo.dto.role.*;
import com.boatAnchorAssistant.service.repository.in.AuthorizationRepository;
import com.boatAnchorAssistant.service.repository.in.RoleRepository;
import com.boatAnchorAssistant.service.service.in.AuthorizationService;
import com.boatAnchorAssistant.service.service.in.RoleService;
import nirvana.core.domains.vo.PageResult;
import nirvana.core.exceptions.BizException;
import nirvana.core.utils.ids.IdGenerator;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import java.util.ArrayList;
import java.util.List;

/**
 * 【描 述】：角色服务
 * 【环 境】：J2SE 17
 * 【详 细】：
 *
 */
@Service
public class RoleServiceImpl implements RoleService {

    private final RoleRepository roleRepository;

    private final AuthorizationService authorizationService;

    private final AuthorizationRepository authorizationRepository;

    private final ApplicationEventPublisher publisher;

    public RoleServiceImpl(RoleRepository roleRepository, AuthorizationService authorizationService, AuthorizationRepository authorizationRepository, ApplicationEventPublisher publisher) {
        this.roleRepository = roleRepository;
        this.authorizationService = authorizationService;
        this.authorizationRepository = authorizationRepository;
        this.publisher = publisher;
    }


    /**
     * 创建角色
     *
     * @param param
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createRole(CreateRoleParam param) {
        Role role = new Role();
        BeanUtils.copyProperties(param, role);
        Long id = IdGenerator.SNOW.generate();
        role.setId(id);
        role.setIsDisable(!param.getEnabled());
        roleRepository.create(role);

        List<Long> resourceIds = param.getResourceIds();


        //保存授权
        AuthorizationParam authorizationParam = new AuthorizationParam();
        authorizationParam.setTargetId(id);
        authorizationParam.setResourceIds(resourceIds);
        authorizationService.authorization(authorizationParam);
    }

    /**
     * 修改角色
     *
     * @param param
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editRole(EditRoleParam param) {
        Long id = param.getId();
        Role role = roleRepository.getByIdCheck(id);
        BeanUtils.copyProperties(param, role);
        role.setIsDisable(!param.getEnabled());
        roleRepository.edit(role);

        List<Long> resourceIds = param.getResourceIds();

        //保存授权
        AuthorizationParam authorizationParam = new AuthorizationParam();
        authorizationParam.setTargetId(id);
        authorizationParam.setResourceIds(resourceIds);
        authorizationService.authorization(authorizationParam);
    }

    /**
     * 移除角色
     *
     * @param id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeRole(Long id) {
        roleRepository.removeById(id);

        DeleteRoleEvent event = new DeleteRoleEvent();
        event.setRoleId(id);

        publisher.publishEvent(event);
    }

    /**
     * 启动/禁用角色
     *
     * @param id
     */
    @Override
    public void enabledRole(Long id) {
        Role role = roleRepository.getByIdCheck(id);
        role.setIsDisable(!role.getIsDisable());
        roleRepository.edit(role);
    }

    /**
     * 获取角色详情
     *
     * @param id
     * @return
     */
    @Override
    public GetRoleVo getRole(Long id) {
        Role role = roleRepository.getByIdCheck(id);
        GetRoleVo vo = new GetRoleVo();
        BeanUtils.copyProperties(role, vo);
        vo.setEnabled(!role.getIsDisable());

        //获取相关资源
        GetAuthorizedByTargetIdDto dto = new GetAuthorizedByTargetIdDto();
        dto.setTargetId(id);
        List<Long> resourceIds = authorizationRepository.getTargetAuthorizedList(dto);
        vo.setResourceIds(resourceIds);

        return vo;
    }

    /**
     * 获取角色 列表
     *
     * @param param
     * @return
     */
    @Override
    public PageResult<GetRoleListVo> getRoleList(GetRoleListParam param) {

        SelectRoleDto dto = new SelectRoleDto();
        BeanUtils.copyProperties(param, dto);
        Page<Role> page = roleRepository.selectRole(dto);
        List<Role> roleList = page.getRecords();
        List<GetRoleListVo> list = new ArrayList<>();
        for (Role role : roleList) {
            GetRoleListVo vo = new GetRoleListVo();
            BeanUtils.copyProperties(role, vo);

            vo.setEnabled(!role.getIsDisable());

            list.add(vo);
        }
        return new PageResult<>(list, page);

    }

    /**
     * 获取角色下拉列表
     *
     * @param param
     * @return
     */
    @Override
    public List<GetRoleDownListVo> getRoleDownList(GetRoleDownListParam param) {
        Role po = new Role();
        if (param != null) {
            BeanUtils.copyProperties(param, po);
        }
        List<Role> roleList = roleRepository.getListByEntity(po);

        List<GetRoleDownListVo> list = new ArrayList<>();
        for (Role role : roleList) {
            GetRoleDownListVo vo = new GetRoleDownListVo();
            BeanUtils.copyProperties(role, vo);

            vo.setEnabled(!role.getIsDisable());
            list.add(vo);
        }
        return list;
    }

    /**
     * 创建管理员角色
     *
     * @param dto
     * @return
     */
    @Override
    public void createAdminRole(CreateAdminRoleDto dto) {
        Long tenantId = dto.getTenantId();
        Long departmentId = dto.getDepartmentId();
        Long roleId = dto.getRoleId();


        Role role = new Role();
        role.setId(roleId);
        role.setName("root");
        role.setDepartmentId(departmentId);
        role.setTenantId(tenantId);
        role.setIsSystem(Boolean.TRUE);

        // TODO: 2022-06-27 补充异常
        roleRepository.create(role);
    }

    /**
     * 批量删除角色
     *
     * @param idList
     */
    @Override
    public void bathRemoveRole(List<Long> idList) {
        roleRepository.bathRemoveRole(idList);
    }

    /**
     * 根据部门id删除角色
     *
     * @param departmentIds
     */
    @Override
    public void removeRoleByDepartmentIds(List<Long> departmentIds) {
        roleRepository.removeRoleByDepartmentIds(departmentIds);
    }


}



